package com.ssy.lingxi.order.handler.listener;

import cn.hutool.json.JSONUtil;
import com.rabbitmq.client.Channel;
import com.ssy.lingxi.dto.model.constant.SettleAccountsConstant;
import com.ssy.lingxi.order.api.model.constant.OrderFeignConstant;
import com.ssy.lingxi.product.api.feign.IGoodsPriceFeign;
import com.ssy.lingxi.product.api.model.request.price.OrderPriceRequest;
import com.ssy.lingxi.order.model.constant.OrderQueueMessageTypeEnum;
import com.ssy.lingxi.order.model.constant.OrderServiceContants;
import com.ssy.lingxi.order.model.dto.OrderQueueDTO;
import com.ssy.lingxi.order.service.base.IBaseOrderScheduleService;
import com.ssy.lingxi.order.utils.OrderStringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * 消息队列监听类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-10-21
 */
@Component
public class MessageQueueListener {
    private final static Logger logger = LoggerFactory.getLogger(MessageQueueListener.class);

    @Resource
    private IBaseOrderScheduleService baseOrderScheduleService;

    @Resource
    private IGoodsPriceFeign goodsPriceFeign;

    /**
     * 内部延迟队列消费者
     * @param message 消息
     * @param channel  消息通道
     */
    @RabbitListener(queues = OrderServiceContants.ORDER_SERVICE_DELAY_QUERY, ackMode = "MANUAL")
    public void handler(Message message, Channel channel) {
        try {
            String jsonMessage = new String(message.getBody());
            logger.info("内部延迟队列接收到消息 => " + jsonMessage);

            OrderQueueDTO queueDTO = OrderStringUtil.deserializeObject(jsonMessage, OrderQueueDTO.class);
            if(Objects.isNull(queueDTO) || Objects.isNull(queueDTO.getType()) || !StringUtils.hasLength(queueDTO.getMessage())) {
                logger.info("内部延迟队列消息反序列化后错误 => " + jsonMessage);
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
                return;
            }

            //根据延迟时间判断是否需要重新加入队列
            if(baseOrderScheduleService.reScheduleDelayMessage(queueDTO)) {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
                return;
            }

            OrderQueueMessageTypeEnum messageType = OrderQueueMessageTypeEnum.parse(queueDTO.getType());
            switch (messageType) {
                case AUTO_CANCEL:
                    baseOrderScheduleService.orderCancel(queueDTO.getMessage());
                    break;
                case AUTO_RECEIVE:
                    baseOrderScheduleService.scheduleOrderReceive(queueDTO.getMessage());
                    break;
                case PAYMENT_QUERY:
                    baseOrderScheduleService.orderQueueCallback(queueDTO.getTimes(), queueDTO.getMessage());
                    break;
                default:
                    break;
            }

            //确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
        } catch (Exception e){
            logger.error("内部延迟队列接收消息错误：" + e.getMessage());
        }
    }

    /**
     * 订单支付回调通知队列
     * @param message 消息
     * @param channel  消息通道
     */
    @RabbitListener(queues = OrderFeignConstant.ORDER_PAY_CALLBACK_QUERY, ackMode = "MANUAL")
    public void orderPayCallbackHandler(Message message, Channel channel) {
        try {
            baseOrderScheduleService.orderPayCallback(new String(message.getBody()));

            //确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
        } catch (Exception e){
            logger.error("订单支付回调，从消息队列接收消息错误：" + e.getMessage());
        }
    }

    /**
     * 订单拼团结果异步通知
     * @param message 消息
     * @param channel  消息通道
     */
    @RabbitListener(queues = OrderFeignConstant.ORDER_GROUP_QUERY, ackMode = "MANUAL")
    public void orderGroupHandler(Message message, Channel channel) {
        try {
            baseOrderScheduleService.updateOrderGroupStatus(new String(message.getBody()));

            //确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
        } catch (Exception e){
            logger.error("从消息队列接收拼团订单消息错误：" + e.getMessage());
        }
    }

    /**
     * 营销服务更新支付记录结算状态异步通知
     * @param message 消息
     * @param channel  消息通道
     */
    @RabbitListener(queues = SettleAccountsConstant.SA_PLATFORM_SETTLEMENT_ALL_IN_PAY_QUEUE, ackMode = "MANUAL")
    public void paymentSettlementStatusHandler(Message message, Channel channel) {
        try {
            baseOrderScheduleService.updateOrderPaymentStatus(new String(message.getBody()));
            //确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
        } catch (Exception e){
            logger.error("从消息队列接收营销服务更新支付记录结算状态消息错误：" + e.getMessage());
        }
    }

    /**
     * 采购询价合同、采购竞价合同、采购招标合同、请购单采购 确认收货时, 同步更新物料价格库
     * @param message 消息
     * @param channel  消息通道
     */
    @RabbitListener(queues = OrderServiceContants.ORDER_GOODS_PRICE_CHANGE_QUEUE, ackMode = "MANUAL")
    public void goodsPriceChangeReceive(Message message, Channel channel) {
        OrderPriceRequest request = JSONUtil.toBean(new String(message.getBody()), OrderPriceRequest.class);
        logger.info("订单确认收货时,更新物料价格信息- 开始处理:接受内容:{}", message.getBody());
        try {
            goodsPriceFeign.changeOrderGoodsPrice(request);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
            logger.info("订单确认收货时,更新物料价格信息- 处理完成");
        } catch (Exception e) {
            logger.error("============订单确认收货时,更新物料价格信息 MQ消费失败==============");
            logger.error(e.getMessage());
        }

    }
}
